package com.yu.processor;


import com.yu.ApplicationContext;
import com.yu.annotion.*;
import com.yu.bean.BeanDefinition;
import com.yu.commoninterface.BeanPostProcessor;
import com.yu.util.ClassUtil;

import java.util.*;
import java.util.stream.Collectors;

public class ScanProcessor {

    // 扫描的起始类
    private Class<?> scanClass;

    // 所有的Bean后置处理器
    private List<String> beanPostProcessorBeanNames = new ArrayList<>();

    // 所有aop处理Bean
    private List<BeanDefinition> aspectBeanDefinitions = new ArrayList<>();

    public List<String> getBeanPostProcessorBeanNames() {
        return this.beanPostProcessorBeanNames;
    }

    public List<BeanDefinition> getAspectBeanDefinitions() {
        return this.aspectBeanDefinitions;
    }

    public ScanProcessor(Class<?> clazz, Map<String, BeanDefinition> beanDefinitionMap) {
        System.out.println("[spring] 扫描起始类所在包下的所有类...");
        this.scanClass = clazz;

        if (scanClass.isAnnotationPresent(ComponentScan.class)) {
            ComponentScan componentScan = scanClass.getAnnotation(ComponentScan.class);
            String basePackage = componentScan.basePackage();
            if ("".equals(basePackage)) // 没有指定要扫描的起点包就从起始类所在包开始扫描
                basePackage = clazz.getPackage().getName();
            Set<Class<?>> classes = ClassUtil.getClasses(basePackage); // 获取包下所有Class

            for (Class<?> c : classes)
                if (c.isAnnotationPresent(Component.class))
                    registerBeanDefinition(c, beanDefinitionMap);

            // 内置的Component组件
            registerBeanDefinition(AspectAutoProxyBeanProcessor.class, beanDefinitionMap);
        } else {
            throw new RuntimeException("没有指定扫描的起始类");
        }

        System.out.println("[spring] 扫描完毕 beanDefinitionMap=" + beanDefinitionMap);
        System.out.println("[spring] beanDefinitionMap=" + beanDefinitionMap);
        System.out.println("[spring] beanPostProcessorBeanNames=" + beanPostProcessorBeanNames);
        System.out.println("[spring] aspectBeanDefinitions=" + aspectBeanDefinitions);
    }


    // TODO 普通方式 注册BeanDefinition, clazz必须含有@Component注解
    private void registerBeanDefinition(Class<?> c, Map<String, BeanDefinition> beanDefinitionMap) {
        String beanName = c.getAnnotation(Component.class).value();
        BeanDefinition beanDefinition = new BeanDefinition();
        beanDefinition.setBeanClass(c);
        beanName = "".equals(beanName) ? ClassUtil.getBeanName(c.getSimpleName()) : beanName;
        beanDefinition.setBeanName(beanName);
        Scope scope = c.getDeclaredAnnotation(Scope.class);
        if (scope != null && scope.scopeName() == ScopeName.ENUM_prototype) { // 单例还是多例的
            beanDefinition.setScopeName(ScopeName.ENUM_prototype);
        } else {
            beanDefinition.setScopeName(ScopeName.ENUM_singleton);
        }

        if (BeanPostProcessor.class.isAssignableFrom(c)) // BeanPostProcessor
            beanPostProcessorBeanNames.add(beanName);

        if (c.isAnnotationPresent(Aspect.class)) // 存在aop代理执行器Bean
            aspectBeanDefinitions.add(beanDefinition);

        beanDefinitionMap.put(beanName, beanDefinition);
    }
}
